#include "com_sct_screen_ScreenJni.h"
#include "screen.h"

#include <android/log.h>
#include <GLES/gl.h>

#include "sct/core/common.h"
#include "sct/core/mutex.h"

#define SCT_TAG "sct"

using namespace sct;

enum ScreenState
{
	SS_Terminated = SCT_ENUM_OFFSET,
	SS_Inited,
	SS_Running,
	SS_Stopped,
};

class CScreenInfo
{
public:
	CMutex * mMutex;
	uint8_t * mData;
	int mMaxLen;
	int mPictureHeight;
	int mPictureWidth;

	ScreenState mState;

	int mWidth;
	int mHeight;

	int mNeedDeleteTexture;
	GLuint mTextures[1];
};

static CScreenInfo * gScreenInfo = NULL;

JNIEXPORT void JNICALL Java_com_sct_screen_ScreenJni_create
  (JNIEnv *, jclass)
{
	if(NULL != gScreenInfo) return;

	gScreenInfo = new CScreenInfo;
	gScreenInfo->mMutex = new CMutex;

	gScreenInfo->mState = SS_Terminated;
	gScreenInfo->mWidth = 0;
	gScreenInfo->mHeight = 0;

	gScreenInfo->mNeedDeleteTexture = 0;
	gScreenInfo->mTextures[0] = -1;

	GLint mx;
	glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mx);///the value is wrong.
	SCT_LOGD("glGetIntegerv return:%d", mx);

	mx = 2048;

	SCT_LOGD("mx set to:%d", mx);

	///RGBA
	gScreenInfo->mMaxLen = mx * mx * 4;

	gScreenInfo->mData = new uint8_t[gScreenInfo->mMaxLen];
	bzero(gScreenInfo->mData, gScreenInfo->mMaxLen);

	gScreenInfo->mPictureHeight = 240;
	gScreenInfo->mPictureWidth = 320;

	gScreenInfo->mState = SS_Inited;
}

JNIEXPORT void JNICALL Java_com_sct_screen_ScreenJni_destroy
  (JNIEnv *, jclass)
{
	CMutex * p = gScreenInfo->mMutex;
	p->lock();

	if(gScreenInfo->mNeedDeleteTexture)
	{
		glDeleteTextures(1, gScreenInfo->mTextures);
		gScreenInfo->mNeedDeleteTexture = 0;
	}

	SCT_DELETE_ARRAY(gScreenInfo->mData);
	SCT_DELETE(gScreenInfo);

	p->unlock();
	SCT_DELETE(p);
}


JNIEXPORT void JNICALL Java_com_sct_screen_ScreenJni_tryToShowOneFrame
  (JNIEnv * env, jclass clx)
{
	///init for draw
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	//glTranslatef(0.0f, 0.0f, -1.2f);


	///delete old texture and create a new one
	if(gScreenInfo->mNeedDeleteTexture)
	{
		glDeleteTextures(1, gScreenInfo->mTextures);
		gScreenInfo->mNeedDeleteTexture = 0;
	}

	glGenTextures(1, gScreenInfo->mTextures);
	gScreenInfo->mNeedDeleteTexture = 1;

	glBindTexture(GL_TEXTURE_2D, gScreenInfo->mTextures[0]);

	GLint mx;
	glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mx);
	mx = 1024;

	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, mx, mx, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

	gScreenInfo->mMutex->lock();

	int w = gScreenInfo->mPictureWidth;
	int h = gScreenInfo->mPictureHeight;
	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, gScreenInfo->mData);

	gScreenInfo->mMutex->unlock();

	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

	GLfloat textureCoords[8] =
	{
			0.0f, 1.0f,
			1.0f, 1.0f,

			0.0f, 0.0f,
			1.0f, 0.0f,
	};


	textureCoords[0] = 0.0;			textureCoords[1] = (1.0*h)/mx;
	textureCoords[2] = (1.0*w)/mx;	textureCoords[3] = (1.0*h)/mx;
	textureCoords[4] = 0.0;			textureCoords[5] = 0.0;
	textureCoords[6] = (1.0*w)/mx;	textureCoords[7] = 0.0;

	glTexCoordPointer(2, GL_FLOAT, 0, textureCoords);

	float vertices[] =           //2
	{
			-1.0f, -1.0f,
			1.0f, -1.0f,
			-1.0f,  1.0f,
			1.0f,  1.0f
	};

	float x = 1;
	float y = 1;

	float winRatio = (1.0*gScreenInfo->mHeight)/(1.0*gScreenInfo->mWidth);
	float picRatio = (1.0*h) / w;

	if(winRatio > picRatio)
	{
		x = 1;
		y = picRatio;
	}
	else
	{
		x = 1 * (winRatio/picRatio);
		y = winRatio;
	}


	vertices[0] = -x;	vertices[1] = -y;
	vertices[2] = x;	vertices[3] = -y;
	vertices[4] = -x;	vertices[5] = y;
	vertices[6] = x;	vertices[7] = y;

	glVertexPointer(2, GL_FLOAT, 0, vertices);

	glEnable(GL_TEXTURE_2D);

	//glEnable(GL_BLEND);
	glBlendFunc(GL_ONE, GL_SRC_COLOR);

	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	glEnableClientState(GL_VERTEX_ARRAY);
	glDisableClientState(GL_COLOR_ARRAY);
	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	glDisableClientState(GL_VERTEX_ARRAY);

}

JNIEXPORT void JNICALL Java_com_sct_screen_ScreenJni_configScreen
  (JNIEnv * env, jclass clx, jint w, jint h, jint t)
{
	gScreenInfo->mState = SS_Running;

	gScreenInfo->mWidth = w;
	gScreenInfo->mHeight = h;

	glDisable(GL_DITHER);
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);

	if(t)
	{
		glClearColor(0, 0, 0, 0);
	}
	else
	{
		glClearColor(1, 1, 1, 1);
	}

	glEnable(GL_CULL_FACE);
	glShadeModel(GL_SMOOTH);
	glEnable(GL_DEPTH_TEST);

	glViewport(0, 0, w, h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	float x = 1.0;
	float y = (1.0 * h)/w;

	//in the center
	glOrthof(-x, x, -y, y, 1, -1);

}

void sct_screen_putdata(const void * d, const int len, const int w, const int h)
{
	CAutoLock locker(gScreenInfo->mMutex);

	memcpy(gScreenInfo->mData, d, len);
	gScreenInfo->mPictureHeight = h;
	gScreenInfo->mPictureWidth = w;
}
